import { reactive, Ref, nextTick, ComputedRef } from "vue";
import { ImgToolsType, CanvasConfigType, CropperType } from "@/components/imgTools/types/type";
import { deepCopy } from "@/utils";

/**
 *
 * @param imgWidth 图片宽度
 * @param imgHeight 图片高度
 * @param toolOptions 初始配置对象
 * @param imgBox Image对象
 * @param canvasRef canvasRef
 * @param ctx canvas上下文
 * @param imgHistoryList 历史图片存储数组
 * @param currentImg 当前图片下标
 * @param setImgOptions 图片参数保存方法
 * @returns
 */
export const useImgCopper = (
    imgWidth: Ref<number>,
    imgHeight: Ref<number>,
    toolOptions: ImgToolsType,
    imgBox: HTMLImageElement,
    canvasRef: Ref<HTMLCanvasElement | undefined>,
    ctx: ComputedRef<CanvasRenderingContext2D>,
    imgHistoryList: Ref<CanvasConfigType[]>,
    currentImg: Ref<number>,
    setImgOptions:Function
) => {
    // 裁切框样式
    const cropperStyle = reactive<CropperType>({
        width: 0,//裁切框的宽度
        height: 0,//裁切框的高度
        //裁切框的左上角位置
        left: 0,
        top: 0,
        // 图片的左上角位置
        imgLeft:0,
        imgTop:0,
        cutLineOpacity: 0,//分割线透明度
        isReset:false,//是否可以重置
        rotate:0,//旋转的弧度
        bigWidth:0,//旋转后放大的图片宽度
        bigHeight: 0,//旋转后放大的图片高度
        scale: 1,//旋转后放大的图片倍数
        degree:0,//旋转的角度
    });
    // 裁剪框位置初始值
    let cropperWidth = 0
    let cropperHeight = 0
    let cropperLeft = 0
    let cropperTop = 0

    const addEventListener = () => {
        nextTick(() => {
            document.querySelector(".left-top-border")?.addEventListener("mousedown", (el: any) => moveCropDom("left-top", el))
            document.querySelector(".left-bottom-border")?.addEventListener('mousedown', (el: any) => moveCropDom('left-bottom', el))
            document.querySelector(".right-top-border")?.addEventListener('mousedown', (el: any) => moveCropDom('right-top', el))
            document.querySelector(".right-bottom-border")?.addEventListener('mousedown', (el: any) => moveCropDom('right-bottom', el))
            document.querySelector(".top-middle-border")?.addEventListener('mousedown', (el: any) => moveCropDom('top-middle', el))
            document.querySelector(".left-middle-border")?.addEventListener('mousedown', (el: any) => moveCropDom('left-middle', el))
            document.querySelector(".right-middle-border")?.addEventListener('mousedown', (el: any) => moveCropDom('right-middle', el))
            document.querySelector(".bottom-middle-border")?.addEventListener('mousedown', (el: any) => moveCropDom('bottom-middle', el))
        })
    }

    const handleCropper = (config: CanvasConfigType) => {
        cropperWidth = config.width ? config.width * toolOptions.zoom : imgWidth.value
        cropperHeight = config.height ? config.height * toolOptions.zoom : imgHeight.value
        cropperLeft = config.left * toolOptions.zoom
        cropperTop = config.top * toolOptions.zoom
        cropperStyle.width = cropperWidth
        cropperStyle.height = cropperHeight
        cropperStyle.left = cropperLeft
        cropperStyle.top = cropperTop
        addEventListener()
        nextTick(() => handleRotate(config.degree,cropperStyle.isReset))
    }

    const handleResetCropper = () => {
        cropperStyle.width = 0
        cropperStyle.height = 0
        cropperStyle.left = 0
        cropperStyle.top = 0
        cropperStyle.cutLineOpacity = 0
        cropperStyle.isReset = false
        cropperWidth = 0
        cropperHeight = 0
        cropperLeft = 0
        cropperTop = 0
    }

    // 设置蒙层，确定裁剪区域
    const setCutPart = () => {
        const imgRealWidth = imgWidth.value
        const imgRealHeight = imgHeight.value
        const bigHeight = cropperStyle.bigHeight
        const bigWidth = cropperStyle.bigWidth
        const rotate = cropperStyle.rotate
        // 绘制前清除画布
        ctx.value.resetTransform()
        ctx.value.clearRect(0, 0, canvasRef.value!.width, canvasRef.value!.height)
        // 旋转画布
        ctx.value.translate(canvasRef.value!.width / 2, canvasRef.value!.height / 2)
        ctx.value.rotate(rotate)
        // 设置蒙层
        ctx.value.fillStyle = `rgba(255,255,255,${toolOptions.opacity})`
        ctx.value.fillRect(-cropperStyle.imgLeft, -cropperStyle.imgTop, bigWidth, bigHeight)
        // 绘制裁剪部分图层(destination-out可以理解为在已绘制图像上擦除一部分)
        ctx.value.globalCompositeOperation = 'destination-out'
        ctx.value.rotate(-rotate)
        ctx.value.fillStyle = '#2c2c2c'
        ctx.value.fillRect(cropperStyle.left - imgRealWidth / 2, cropperStyle.top - imgRealHeight / 2, cropperStyle.width, cropperStyle.height)
        // 绘制图片(destination-over表示将新的图像绘制到已有图像下方)
        ctx.value.globalCompositeOperation = 'destination-over'
        ctx.value.rotate(rotate)
        ctx.value.drawImage(imgBox, -cropperStyle.imgLeft, -cropperStyle.imgTop, bigWidth, bigHeight)
    }

    const moveCropDom = (key: string, el: any) => {
        el.preventDefault()
        const x = el.clientX;
        const y = el.clientY;
        const imgRealWidth = imgWidth.value
        const imgRealHeight = imgHeight.value
        document.onmousemove = (elMove) => {
            const currentX = elMove.clientX - x;
            const currentY = elMove.clientY - y;
            // 计算边框最多能移动的距离(向bottom,right方向移动)
            const maxMoveWidth = Math.min(Math.max(0, imgRealWidth - cropperWidth - cropperLeft), currentX)
            const maxMoveHeight = Math.min(Math.max(0, imgRealHeight - cropperHeight - cropperTop), currentY)
            cropperStyle.cutLineOpacity = 1
            cropperStyle.isReset = true
            if (key == "left-top") {
                const width = Math.min(cropperLeft, -currentX)
                const height = Math.min(cropperTop, -currentY)
                cropperStyle.width = Math.max(cropperWidth + width,toolOptions.minCropperSize);
                cropperStyle.height = Math.max(cropperHeight + height,toolOptions.minCropperSize);
                if(cropperStyle.width > toolOptions.minCropperSize)
                    cropperStyle.left = Math.min(cropperLeft - width, imgRealWidth - toolOptions.minCropperSize)
                if(cropperStyle.height > toolOptions.minCropperSize)
                    cropperStyle.top = Math.min(cropperTop - height, imgRealHeight - toolOptions.minCropperSize)
            }
            if (key == "left-bottom") {
                const width = Math.min(cropperLeft, -currentX)
                const height = maxMoveHeight
                cropperStyle.width = Math.max(cropperWidth + width, toolOptions.minCropperSize);
                cropperStyle.height = Math.max(cropperHeight + height, toolOptions.minCropperSize);
                if (cropperStyle.width > toolOptions.minCropperSize)
                    cropperStyle.left = Math.min(cropperLeft - width, imgRealWidth - toolOptions.minCropperSize)
            }
            if (key == "right-top") {
                const width = maxMoveWidth
                const height = Math.min(cropperTop, -currentY)
                cropperStyle.width = Math.max(cropperWidth + width, toolOptions.minCropperSize);
                cropperStyle.height = Math.max(cropperHeight + height, toolOptions.minCropperSize);
                if (cropperStyle.height > toolOptions.minCropperSize)
                    cropperStyle.top = Math.min(cropperTop - height, imgRealHeight - toolOptions.minCropperSize)
            }
            if (key == "right-bottom") {
                const width = maxMoveWidth
                const height = maxMoveHeight
                cropperStyle.width = Math.max(cropperWidth + width, toolOptions.minCropperSize);
                cropperStyle.height = Math.max(cropperHeight + height, toolOptions.minCropperSize);
            }
            if (key == "top-middle") {
                const height = Math.min(cropperTop, -currentY)
                cropperStyle.height = Math.max(cropperHeight + height, toolOptions.minCropperSize)
                if (cropperStyle.height > toolOptions.minCropperSize)
                    cropperStyle.top = Math.min(cropperTop - height, imgRealHeight - toolOptions.minCropperSize)
            }
            if (key == "right-middle") {
                const width = maxMoveWidth
                cropperStyle.width = Math.max(cropperWidth + width, toolOptions.minCropperSize);
            }
            if (key == "bottom-middle") {
                const height = maxMoveHeight
                cropperStyle.height = Math.max(cropperHeight + height, toolOptions.minCropperSize)
            }
            if (key == "left-middle") {
                const width = Math.min(cropperLeft, -currentX)
                cropperStyle.width = Math.max(cropperWidth + width, toolOptions.minCropperSize);
                if (cropperStyle.width > toolOptions.minCropperSize)
                    cropperStyle.left = Math.min(cropperLeft - width, imgRealWidth - toolOptions.minCropperSize)
            }
            // 设置图片的蒙层
            setCutPart()
        }
        document.onmouseup = () => {
            document.onmousemove = document.onmouseup = null;
            // 存储一下当前裁剪框的宽高和位置
            cropperWidth = cropperStyle.width
            cropperHeight = cropperStyle.height
            cropperTop = cropperStyle.top
            cropperLeft = cropperStyle.left
            cropperStyle.cutLineOpacity = 0
            confirmCropper()
        };

    };

    //旋转
    const handleRotate = (degree:number,reset:boolean = true) => {
        if(reset) cropperStyle.isReset = true
        // 转为弧度制
        const rotate = (degree < 0 ? -degree : degree) * Math.PI / 180

        const imgRealWidth = imgWidth.value
        const imgRealHeight = imgHeight.value
        let scale = 1
        //图片宽度大于高度，计算高度比值，反之计算宽度比值
        if(imgRealWidth > imgRealHeight){
            // 放大后的图片高度(1/2)
            const scaleHeight = Math.sin(rotate) * (imgRealWidth / 2 - imgRealHeight / 2 * Math.tan(rotate)) + imgRealHeight / 2 / Math.cos(rotate)
            // 旋转图片需要放大的倍数
            scale = scaleHeight / (imgRealHeight / 2)
        }else{
            const scaleWidth = imgRealWidth / 2 / Math.cos(rotate) + (imgRealHeight / 2 - imgRealWidth / 2 * Math.tan(rotate)) * Math.sin(rotate)
            scale = scaleWidth / (imgRealWidth / 2)
        }
        // 放大后的宽高
        const bigWidth = imgRealWidth * scale
        const bigHeight = imgRealHeight * scale
        // 存储一下
        cropperStyle.degree = degree
        cropperStyle.bigHeight = bigHeight
        cropperStyle.bigWidth = bigWidth
        cropperStyle.scale = scale
        cropperStyle.rotate = degree < 0 ? -rotate : rotate
        cropperStyle.imgLeft = cropperStyle.bigWidth / 2
        cropperStyle.imgTop = cropperStyle.bigHeight / 2
        // console.log(cropperStyle.imgLeft, cropperStyle.imgTop, cropperStyle.bigWidth / 2,cropperStyle.bigHeight / 2)
        // 设置蒙层
        setCutPart()
    }

    // 裁切
    const confirmCropper = () => {
        return new Promise<string>((resolve) => {
            // 计算出原始图片裁剪的位置和宽高
            const left = (cropperStyle.bigWidth / 2 - imgWidth.value  / 2 + cropperLeft)*imgBox.width/cropperStyle.bigWidth
            const top = (cropperStyle.bigHeight / 2 - imgHeight.value  / 2 + cropperTop)*imgBox.height/cropperStyle.bigHeight
            const width = cropperWidth / cropperStyle.bigWidth * imgBox.width
            const height = cropperHeight / cropperStyle.bigHeight * imgBox.height
            // 创建一个canvas,绘制原图，进行变换
            const canvas = document.createElement('canvas');
            const ctx = canvas.getContext('2d')
            canvas.width = imgBox.width
            canvas.height = imgBox.height
            ctx?.translate(imgBox.width/2, imgBox.height/2)
            ctx?.rotate(cropperStyle.rotate)
            ctx?.drawImage(imgBox, -imgBox.width / 2, -imgBox.height / 2, imgBox.width, imgBox.height);
            // 创建一个新的canvas用来裁剪
            const cutCanvas = document.createElement('canvas');
            const cutCtx = cutCanvas.getContext('2d')
            cutCanvas.width = width
            cutCanvas.height = height
            cutCtx?.drawImage(canvas,left,top,width,height,0,0,width,height)
            const url = cutCanvas.toDataURL('image/jpeg')
            // 存储当前canvas配置
            const config = deepCopy(imgHistoryList.value[currentImg.value])
            config.width = cropperStyle.width
            config.height = cropperStyle.height
            config.left = cropperStyle.left
            config.top = cropperStyle.top
            config.degree = cropperStyle.degree
            config.url = url
            // console.log(url)
            setImgOptions(config)
            resolve(url)
        })
    }

    return {
        cropperStyle,
        setCutPart,
        handleCropper,
        handleResetCropper,
        confirmCropper,
        handleRotate,
    }
}